import json
import logging

from django.conf import settings
from django.http import JsonResponse
from django.views import View
from django_redis import get_redis_connection

from carts.utils import get_carts_from_cookies, get_carts_cookie_data,get_redis_carts
from goods.models import SKU

logger = logging.getLogger("django")

# Create your views here.


class CartsView(View):

    def post(self, request):
        """
        添加商品到购物车
        :param request:
        :return:
        """
        '''获取请求参数'''
        request_data = json.loads(request.body)
        sku_id = request_data.get("sku_id")  # 商品id
        count = request_data.get("count")  # 商品数量
        selected = request_data.get("selected", True)  # 勾选状态

        '''检查请求参数'''
        try:
            int(sku_id)
            count = int(count)
            if not isinstance(selected, bool):
                selected = True  # 默认勾选当前商品
        except Exception as e:
            logger.error(f"请求参数有误：{e}")
            return JsonResponse({"code": 400, "errmsg": "请求参数有误"})

        '''
        如果当前用户已登录
        则将购物车数据保存到数据库
        如果当前用户未登录
        则将购物车数据保存到cookie
        '''
        user = request.user  # 获取当前用户
        response = JsonResponse({"code": 0, "errmsg": "OK"})  # 构建响应体
        if user.is_authenticated:
            redis_conn = get_redis_connection("carts")  # 获取redis连接对象
            # sku_count = redis_conn.hget(f"carts_{user.id}", sku_id)  # 获取当前商品已添加数量
            # if sku_count:  # 如果当前商品已添加过购物车，则把已添加的数量和当前添加的数量相加
            #     count += int(sku_count)
            pip = redis_conn.pipeline()  # 创建管道
            # 使用hash类型存储用户购物车商品及其数量{name key field value [field value ...]}
            pip.hincrby(f"carts_{user.id}", sku_id, count)  # count值会自动累加
            if selected:
                # 使用set类型存储用户已勾选商品{key member [member ...]}
                pip.sadd(f"selected_{user.id}", sku_id)
            try:
                pip.execute()  # 执行管道
            except Exception as e:
                logger.error(f"添加购物车失败:{e}")
                return JsonResponse({"code": 400, "errmsg": "添加购物车失败"})
        else:
            carts_cookie = get_carts_from_cookies(request)  # 从cookie获取用户购物车数据
            carts_sku = carts_cookie.get(sku_id)
            if carts_sku:  # 如果当前商品已添加过购物车，则把已添加的数量和当前添加的数量相加
                sku_count = carts_sku.get("count")
                count += sku_count
            carts_cookie[sku_id] = {
                "count": count,
                "selected": selected
            }
            carts_data = get_carts_cookie_data(carts_cookie)  # 编码cookie购物车数据
            response.set_cookie(settings.COOKIE_CART, carts_data)  # 设置cookie，在cookie中加入购物车信息

        '''返回响应信息'''
        return response

    def get(self, request):
        """
        获取购物车商品
        :param request:
        :return:
        """
        '''
        如果当前用户已登录
        则从数据库获取购物车数据
        如果当前用户未登录
        则从cookie中获取购物车数据
        '''
        user = request.user  # 获取当前用户
        if user.is_authenticated:  # 用户已登录
            redis_conn = get_redis_connection("carts")  # 获取redis连接对象
            carts_user = redis_conn.hgetall(f"carts_{user.id}")  # 获取用户购物车数据
            if not carts_user:
                return JsonResponse({"code": 400, "errmsg": "购物车是空的"})
            sku_id_list = carts_user.keys()  # 获取购物车中所有商品的id(字节类型)
            # 定义一个字典整理购物车数据，使其和cookie购物车数据一致，方便统一处理
            carts_dict = {}
            for sku_id in sku_id_list:
                carts_dict[int(sku_id)] = {
                    "count": int(carts_user[sku_id]),
                    "selected": sku_id in redis_conn.smembers(f"selected_{user.id}")
                }
        else:  # 用户未登录
            carts_dict = get_carts_from_cookies(request)  # 从cookie中获取用户购物车数据
            if not carts_dict:
                return JsonResponse({"code": 400, "errmsg": "购物车是空的"})

        '''提取商品信息'''
        cart_skus = []  # 定义列表存储商品信息
        sku_id_list = carts_dict.keys()  # 获取购物车中所有商品id
        for sku_id in sku_id_list:
            try:
                sku = SKU.objects.get(id=sku_id)  # 获取商品对象
            except Exception as e:
                logger.error(f"此商品(ID:{sku_id})不存在:{e}")
                continue
            cart_skus.append({
                "id": sku_id,  # 商品id
                "name": sku.name,  # 商品名称
                "count": carts_dict.get(sku_id).get("count"),  # 商品数量
                "selected": carts_dict[sku_id]["selected"],  # 勾选状态
                "default_image_url": sku.default_image_url,  # 商品连接
                "price": sku.price,  # 商品价格
                # "amount": None  # 商品总价
            })  # 添加商品信息

        '''返回响应数据'''
        return JsonResponse({
            "code": 0,
            "errmsg": "OK",
            "cart_skus": cart_skus
        })

    def put(self, request):
        """
        修改购物车商品勾选状态
        :param request:
        :return:
        """

        # 1、提取参数
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected', True)

        # 2、校验参数
        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '缺少参数！'})

        if isinstance(sku_id, str) and not sku_id.isdigit():
            return JsonResponse({'code': 400, 'errmsg': '参数错误！'})

        if isinstance(count, str) and not count.isdigit():
            return JsonResponse({'code': 400, 'errmsg': '参数错误！'})

        if not isinstance(selected, bool):
            return JsonResponse({'code': 400, 'errmsg': '参数错误！'})

        # 3、数据处理
        if request.user.is_authenticated:
            # 3.1 用户已登陆
            # sku_id, count, selected
            # 修改redis购物车中sku_id对应的count值
            conn = get_redis_connection('carts')
            conn.hset('carts_%s' % request.user.id, sku_id, count)
            if selected:
                # 把sku_id加入redis的集合中表示选中
                conn.sadd('selected_%s' % request.user.id, sku_id)
            else:
                # 把sku_id从redis集合中去除，表示取消选中
                conn.srem('selected_%s' % request.user.id, sku_id)

            return JsonResponse({
                'code': 0,
                'errmsg': 'ok',
                'cart_sku': {
                    'id': sku_id,
                    'count': count,
                    'selected': selected
                }
            })

        else:
            # 3.2 用户未登陆
            # {14: {"count": 5, "selected": True}}
            cookie_cart = get_carts_from_cookies(request)

            # {14: {"count": 3, "selected": False}}
            cookie_cart[sku_id]['count'] = count
            cookie_cart[sku_id]['selected'] = selected

            # "ZBHUJgewgrHJUfgrnewjgkrl"
            data = get_carts_cookie_data(cookie_cart)
            response = JsonResponse({
                'code': 0,
                'errmsg': 'ok',
                'cart_sku': {
                    'id': sku_id,
                    'count': count,
                    'selected': selected
                }
            })

            response.set_cookie(
                'carts',
                data
            )
            return response

        # 4、构建响应

    def delete(self, request):
        """
        删除购物车商品
        :param request:
        :return:
        """
        '''获取请求参数'''
        request_data = json.loads(request.body)
        sku_id = request_data.get("sku_id")

        '''检查请求参数'''
        try:
            int(sku_id)
        except Exception as e:
            logger.error(f"请求参数有误:{e}")

        '''删除购物车商品'''
        user = request.user
        response = JsonResponse({"code": 0, "errmsg": "OK"})
        if user.is_authenticated:  # 用户已登录
            redis_conn = get_redis_connection("carts")
            try:
                redis_conn.hdel(f"carts_{user.id}", sku_id)  # 删除商品id
                redis_conn.srem(f"selected_{user.id}", sku_id)  # 删除商品勾选
            except Exception as e:
                logger.error(f"删除商品失败:{e}")
                return JsonResponse({"code": 400, "errmsg": "删除商品失败"})
        else:  # 用户未登录
            carts_cookie = get_carts_from_cookies(request)
            if not carts_cookie:
                return JsonResponse({"code": 400, "errmsg": "购物车是空的"})
            carts_cookie.pop(sku_id)
            carts_data = get_carts_cookie_data(carts_cookie)
            response.set_cookie(settings.COOKIE_CART, carts_data)

        '''返回响应信息'''
        return response


class CartSelectAllView(View):

    def put(self, request):
        """
        修改购物车全选状态
        :param request:
        :return:
        """
        '''获取请求参数'''
        request_data = json.loads(request.body)
        selected = request_data.get("selected")

        '''检查参数'''
        if not isinstance(selected, bool):
            return JsonResponse({"code": 400, "errmsg": "请求参数有误"})

        '''数据处理'''
        user = request.user
        response = JsonResponse({"code": 0, "errmsg": "OK"})
        if user.is_authenticated:  # 用户已登录
            redis_conn = get_redis_connection("carts")  # 获取redis数据库连接对象
            carts_user = redis_conn.hgetall(f"carts_{user.id}")  # 获取购物车数据
            if not carts_user:
                return JsonResponse({"code": 400, "errmsg": "购物车是空的"})
            sku_id_list = carts_user.keys()  # 获取购物车中所有商品的id
            try:
                if selected:
                    redis_conn.sadd(f"selected_{user.id}", *sku_id_list)  # 将购物中所有商品加入勾选状态
                else:
                    redis_conn.srem(f"selected_{user.id}", *sku_id_list)  # 将购物中所有商品取消勾选状态
            except Exception as e:
                logger.error(f"更新勾选状态失败:{e}")
                return JsonResponse({"code": 400, "errmsg": "更新勾选状态失败"})
        else:  # 用户未登录
            carts_cookie = get_carts_from_cookies(request)  # 获取cookie购物车
            if not carts_cookie:
                return JsonResponse({"code": 400, "errmsg": "购物车是空的"})
            try:
                for sku_id in carts_cookie:
                    if selected:
                        carts_cookie[sku_id]["selected"] = True
                    else:
                        carts_cookie[sku_id]["selected"] = False
            except Exception as e:
                logger.error(f"更新全选状态失败:{e}")
                return JsonResponse({"code": 400, "errmsg": "更新全选状态失败"})
            carts_data = get_carts_cookie_data(carts_cookie)
            response.set_cookie(settings.COOKIE_CART, carts_data)

        '''返回响应信息'''
        return response


class CartsSimpleView(View):

    def get(self, request):
        """
        获取简易购物车
        :param request:
        :return:
        """
        '''获取购物车数据'''
        user = request.user
        if user.is_authenticated:  # 用户已登录
            redis_conn = get_redis_connection("carts")
            carts_user = redis_conn.hgetall(f"carts_{user.id}")
            if not carts_user:
                return JsonResponse({"code": 400, "errmsg": "购物车是空的"})
            '''
            整理用户购物车数据
            使用户购物车与cookie购物车一致
            方便统一处理
            '''
            carts_dict = {}
            for sku_id in carts_user:
                carts_dict[int(sku_id)] = {
                    "count": int(carts_user[sku_id]),
                    "selected": sku_id in redis_conn.smembers(f"selected_{user.id}")
                }
        else:  # 用户未登录
            carts_dict = get_carts_from_cookies(request)
            if not carts_dict:
                return JsonResponse({"code": 400, "errmsg": "购物车是空的"})
        '''提取商品信息构建响应体'''
        cart_skus = []
        sku_id_list = carts_dict.keys()
        for sku_id in sku_id_list:
            try:
                sku = SKU.objects.get(id=sku_id)
            except Exception as e:
                logger.error(f"此商品(ID:{sku_id})不存在:{e}")
                continue
            cart_skus.append({
                "id": sku_id,
                "name": sku.name,
                "count": carts_dict[sku_id]["count"],
                "default_image_url": sku.default_image_url
            })

        return JsonResponse({
            "code": 0,
            "errmsg": "OK",
            "cart_skus": cart_skus
        })
